/**
 * Class representing a single declared ui resource for this plugin component
 */
jsx3.lang.Class.defineClass("ux.core.util.component.UIResource",
        jsx3.lang.Object,
        null,
        function(config) {

            /**
             * {String} The path to the UI resource (relative to the plugin's contextRoot)
             * @private
             */
            config.prototype.path = null;

            /**
             * {String} Description of the UI resource
             * @private
             */
            config.prototype.description = null;

            /**
            * {boolean} flag indicating if the UI resource should be hidden in the ACL tree of ActiveMaqtrix Admin UI
            * @private
            */
            config.prototype.hideInACLTree = false;

            /**
             * {jsx3.util.List} List of {String} objects representing extension points contained in this UI resource
             * @private
             */
            config.prototype.extensionPointIDs = null;

            /**
            * {String} User-readable display name of the UI resource
            * @private
            */
            config.prototype.displayName = null;

            /**
             * {jsx3.util.List} List of {String} objects representing extension points this UI resource plugs into
             * @private
             */
            config.prototype.parentExtensionPoints = null;

            /**
             * {jsx3.util.List} List of child {ux.core.util.component.UIResource} objects of this UI resource
             * @private
             */
            config.prototype.UIResources = null;

            /**
            * Indicates whether the original source used extension point wrapper xml (alternate format).  Determines how
            * <code>toString</code> function will write the xml back out again.
            * @private
            */
            config.prototype.useWrappers = false;

            /**
             * Constructor for this class.
             *
             * @param doc {jsx3.xml.Entity} an xml node containing the information for a single UI resource of a plugin component
             * @throws {ux.core.exception.InvalidComponentSchemaException} if the xml is invalid
             */
            config.prototype.init = function(doc) {
                this.jsxsuper();
                this.extensionPointIDs = new jsx3.util.List(0);
                this.parentExtensionPoints = new jsx3.util.List(0);
                this.UIResources = new jsx3.util.List(0);
                var children = doc.getChildNodes().iterator();
                while(children.hasNext()) {
                    var child = children.next();
                    var childName = child.getNodeName();
                    if(childName == "path") {
                        this.path = child.getValue();
                    }
                    else if(childName == "description") {
                        this.description = child.getValue();
                    }
                    else if(childName == "extension_point_ids") {
                        var childIDs = child.getChildNodes().iterator();
                        while(childIDs.hasNext()) {
                            var childID = childIDs.next();
                            if(childID.getNodeName() == "extension_point_id") {
                                this.extensionPointIDs.add(childID.getValue(), this.extensionPointIDs.size());
                            }
                            else if(childID.getNodeName() == "extension_point_id_wrapper") {
                                this.useWrappers = true;
                                var wrapperChildren = childID.getChildNodes().iterator();
                                while(wrapperChildren.hasNext()) {
                                    var wrapperChild = wrapperChildren.next();
                                    if(wrapperChild.getNodeName() == "extension_point_id") {
                                        this.extensionPointIDs.add(wrapperChild.getValue(),this.extensionPointIDs.size());
                                    }
                                    else {
                                        throw new ux.core.exception.InvalidComponentSchemaException("Unknown tag '" + child.getNodeName() + "' in the 'extension_point_id_wrapper' tag of the component schema.  Supported tags are: extension_point_id");
                                    }
                                }
                                if(this.extensionPointIDs.size() == 0) {
                                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'extension_point_id_wrapper' requires at least one 'extension_point_id' child tag")
                                }
                            }
                            else {
                                throw new ux.core.exception.InvalidComponentSchemaException("Unknown tag '" + childID.getNodeName() + "' in the 'extension_point_ids' tag of the component schema.  Supported tags are: extension_point_id, extension_point_id_wrapper");
                            }
                        }
                        if(this.extensionPointIDs.size() == 0) {
                            throw new ux.core.exception.InvalidComponentSchemaException("Tag 'extension_point_ids' requires at least one 'extension_point_id' child tag.")
                        }
                    }
                    else if(childName == "display_name") {
                        this.displayName = child.getValue();
                    }
                    else if(childName == "hide_in_acl_tree") {
                            var value= child.getValue()
                            if(value == "true") {
                               this.hideInACLTree =true
                            }
                            else if(value == "false"){
                                this.hideInACLTree = false
                            }
                            else {
                              throw new ux.core.exception.InvalidComponentSchemaException("Tag 'hide_in_acl_tree' is not a boolean value.")
                            }
                    }
                    else if(childName == "parent_extension_points") {
                        var childPEPs = child.getChildNodes().iterator();
                        while(childPEPs.hasNext()) {
                            var childPEP = childPEPs.next();
                            if(childPEP.getNodeName() == "parent_extension_point") {
                                this.parentExtensionPoints.add(childPEP.getValue(),this.parentExtensionPoints.size());
                            }
                            else if(childPEP.getNodeName() == "parent_extension_point_wrapper") {
                                this.useWrappers = true;
                                var wrapperChildren = childPEP.getChildNodes().iterator();
                                while(wrapperChildren.hasNext()) {
                                    var wrapperChild = wrapperChildren.next();
                                    if(wrapperChild.getNodeName() == "parent_extension_point") {
                                        this.parentExtensionPoints.add(wrapperChild.getValue(),this.parentExtensionPoints.size());
                                    }
                                    else {
                                        throw new ux.core.exception.InvalidComponentSchemaException("Unknown tag '" + child.getNodeName() + "' in the 'parent_extension_point_wrapper' tag of the component schema.  Supported tags are: parent_extension_point");
                                    }
                                }
                                if(this.parentExtensionPoints.size() == 0) {
                                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'parent_extension_point_wrapper' requires at least one 'parent_extension_point' child tag")
                                }
                            }
                            else {
                                throw new ux.core.exception.InvalidComponentSchemaException("Unknown tag '" + child.getNodeName() + "' in the 'parent_extension_points' tag of the component schema.  Supported tags are: parent_extension_point");
                            }
                        }
                        if(this.parentExtensionPoints.size() == 0) {
                            throw new ux.core.exception.InvalidComponentSchemaException("Tag 'parent_extension_points' requires at least one 'parent_extension_point' child tag.")
                        }
                    }
                    else if(childName == "ui_resources") {
                        var childUIs = child.getChildNodes().iterator();
                        while(childUIs.hasNext()) {
                            var childUI = childUIs.next();
                            if(childUI.getNodeName() == "ui_resource") {
                                this.UIResources.add(new ux.core.util.component.UIResource(childUI), this.UIResources.size());
                            }
                        }
                        if(this.UIResources.size() == 0) {
                            throw new ux.core.exception.InvalidComponentSchemaException("Tag 'ui_resources' requires at least one 'ui_resource' child tag.")
                        }
                    }
                    else {
                        throw new ux.core.exception.InvalidComponentSchemaException("Unknown tag '" + childName + "' in the 'ui_resource' tag of the component schema.  Supported tags are: path, description, extension_point_ids, display_name, parent_extension_points, ui_resources, hide_in_acl_tree");
                    }
                }
                if(!this.path) {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'path' is a required child of the 'ui_resource' tag.")
                }
                if(jsx3.util.strTrim(this.path.trim()) == "") {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'path' may not be empty.")
                }
                if(!this.description) {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'description' is a required child of the 'ui_resource' tag.")
                }
                if(jsx3.util.strTrim(this.description.trim()) == "") {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'description' may not be empty.")
                }
                if(!this.displayName) {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'display_name' is a required child of the 'ui_resource' tag.")
                }
                if(jsx3.util.strTrim(this.displayName.trim()) == "") {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'display_name' may not be empty.")
                }
            }

            /**
            * Returns path to this UIResource, relative to the component path.
            *
            * @return {String} the path of this UIResource, relative to the component path.
            */
            config.prototype.getPath = function() {
                return this.path;
            }

            /**
            * Returns the description of this UIResource
            *
            * @return {String} the description of this UIResource
            */
            config.prototype.getDescription = function() {
                return this.description;
            }

            /**
            * Returns a flag indicating whether or not this UIResource should be hidden in the UI ACL tree
            *
            * @return {boolean} flag indicating if this UIResource should be hidden in the UI ACL tree
            */
            config.prototype.isHiddenInACLTree = function() {
                return this.hideInACLTree;
            }

            /**
            * Returns an iterator of the this UIResource's declared Extension Points
            *
            * @return {jsx3.util.Iterator} an iterator of the Extension Point ids {strings} declared by this UIResource
            */
            config.prototype.getExtensionPointIDs = function() {
                return this.extensionPointIDs.clone().iterator();
            }

            /**
            * Returns the display name for this UIResource, used when showing the resource to the user.
            *
            * @return {String} the display name of this UIResource
            */
            config.prototype.getDisplayName = function() {
                return this.displayName;
            }

            /**
            * Returns an iterator of the Extension Points into which this UIResource will 'plugin'.  USed for building the UIResource
            * tree hierarchy.
            *
            * @return {jsx3.util.Iterator} an iterator of Extension Point ids {strings} into which this UIResource will 'plugin'
            */
            config.prototype.getParentExtensionPoints = function() {
                return this.parentExtensionPoints.clone().iterator();
            }

            /**
            * Returns an iterator of all of the child UIResource objects.
            *
            * @return {jsx3.util.Iterator} an iterator for all of the child ux.core.util.component.UIResource objects.
            */
            config.prototype.getUIResources = function() {
                return this.UIResources.clone().iterator();
            }

            /**
            * Returns a string representing this object in the xml format specified by the component.xsd schema
            *
            * @param prepend {String} a string to be prepended to each line of the returned XML (useful for indenting)
            *
            * @returns {String} this Resources object as XML, as specified by the component.xsd schema
            */
            config.prototype.toString = function(prepend) {
                if(!prepend) {
                    prepend = "";
                }
                var ret = prepend + "<ui_resource>\n";
                if(this.description) {
                    ret += prepend + "   <description>" + this.description + "</description>\n";
                }
                if(this.displayName) {
                    ret += prepend + "   <display_name>" + this.displayName + "</display_name>\n";
                }
                if(this.path) {
                    ret += prepend + "   <path>" + this.path + "</path>\n";
                }
                if(this.extensionPointIDs.size() > 0) {
                    ret += prepend + "   <extension_point_ids>\n";
                    var iter = this.extensionPointIDs.iterator();
                    while(iter.hasNext()) {
                        if(this.useWrappers) {
                            ret += prepend + "      <extension_point_id_wrapper>\n";
                            ret += prepend + "         <extension_point_id>" + iter.next().toString() + "</extension_point_id>\n";
                            ret += prepend + "      <extension_point_id_wrapper>\n";
                        }
                        else {
                            ret += prepend + "      <extension_point_id>" + iter.next().toString() + "</extension_point_id>\n";
                        }
                    }
                    ret += prepend + "   </extension_point_ids>\n";
                }
                if(this.parentExtensionPoints.size() > 0) {
                    ret += prepend + "   <parent_extension_points>\n";
                    var iter = this.parentExtensionPoints.iterator();
                    while(iter.hasNext()) {
                        if(this.useWrappers) {
                            ret += prepend + "      <parent_extension_point_wrapper>\n";
                            ret += prepend + "         <parent_extension_point>" + iter.next().toString() + "</parent_extension_point>\n";
                            ret += prepend + "      <parent_extension_point_wrapper>\n";
                        }
                        else {
                            ret += prepend + "      <parent_extension_point>" + iter.next().toString() + "</parent_extension_point>\n";
                        }
                    }
                    ret += prepend + "   </parent_extension_points>\n";
                }
                if(this.UIResources.size() > 0) {
                    ret += prepend + "   <ui_resources>\n";
                    var iter = this.UIResources.iterator();
                    while(iter.hasNext()) {
                        ret += iter.next().toString(prepend + "      ");
                    }
                    ret += prepend + "   </ui_resources>\n";
                }
                if(this.hideInACLTree) {
                    ret += prepend + "   <hide_in_acl_tree>" + this.hideInACLTree + "</hide_in_acl_tree>\n";
                }
                ret += prepend + "</ui_resource>\n";
                return ret;
            }
        }
);